home *** CD-ROM | disk | FTP | other *** search
- Name ccgibm
- ; File CCGIBM.ASM
- ; Tektronix emulator for use with MS Kermit/IBM.
-
- ;CHINESE
- ifdef MSDOS
- include msgibm.dat
- else
- include ccgibm.dat
- endif
- code segment public 'code'
- extrn outchr:near, beep:near, scrseg:near, cmblnk:near
- extrn clrmod:near, savescr:near, cptchr:near, pcwait:near
- extrn restscr:near, getflgs:near, clrbuf:near, vtans52:near
- extrn iseof:near, beep:near
- assume cs:code, ds:datas, es:nothing
-
- ; Initialise TEK mode by setting high resolution screen, etc
-
- tekini PROC NEAR
- push ax ; do presence tests
- push bx
- push cx
- push dx
- push si
- push di
- push es
- mov bx,portval ; get port flow control chars:
- mov bx,[bx].flowc ; bh=xon, bl=xoff or both are nulls
- mov flow,bx ; save here
- mov ax,bx ; get flow control word
- cmp al,0 ; able to do xoff?
- je tekin0 ; e = no
- call outmodem ; tell host xoff while we change modes
- tekin0: mov bx,vtemu.att_ptr ; emulator screen color ptr
- mov al,[bx]
- mov gfcol,al ; save foreground color
- and gfcol,0fh ; save just foreground bits
- and al,70h ; select background color, no bold
- mov cl,4
- shr al,cl ; get background colors
- mov gbcol,al ; set graphics background color
- mov ah,15 ; get current screen mode
- int screen
- cmp al,3 ; in a mono/color text mode (2/3)?
- jbe tekin1 ; be = yes
- cmp al,mono ; mono text mode (7)?
- je tekin1 ; e = yes
- cmp tekflg,0 ; are we active as Tek device now?
- je tekin1 ; e = no
- jmp tekin13 ; yes, don't redo graphics setup
- tekin1: mov curmode,al ; save mode here
- mov ah,3 ; get cursor position
- xor bh,bh ; page 0
- int screen
- mov cursor,dx ; save position
- call savescr ; save text screen
- ; Presence tests.
- tekin2: mov graph_mode,cga ; Color. Assume CGA
- mov segscn,segcga ; assume cga screen segment
- mov gpage,0 ; graphics page 0 but no page 1
- mov putc,offset gputc ; CGA character display routine
- mov gcplot,offset gcgen ; General character plot routine
- mov psetup,offset psetupc ; CGA plot setup routine
- mov plotptr,offset pltcga ; CGA dot plot routine
- mov pincy,offset pincyc ; CGA inc y routine
- mov xmult,5 ; CGA. Scale TEK to PC by 640/1024
- mov xdiv,8 ; so that 0-1023 converts to 0-639
- mov xmax,640-8 ; x-coord of rightmost character
- mov ymult,10 ; vertical scale for IBM is 200/780
- mov ydiv,39 ;
- mov ybot,199 ; Bottom of screen is Y=199
- mov al,tekgraf ; user video board specification
- cmp al,0 ; auto-sensing?
- je tekin2c ; e = yes (default)
- cmp al,1 ; user wants CGA?
- jne tekin2a ; ne = no
- jmp tekin13 ; do CGA
- tekin2a:cmp al,4 ; user wants Hercules?
- jne tekin2b ; ne = no
- jmp tekin8 ; do Hercules
- tekin2b:cmp al,5 ; user wants AT&T style?
- jne tekin2c ; ne = no
- jmp tekin7 ; do AT&T kind
- ; do auto-sensing of display board
- ; test for EGA
- tekin2c:mov ax,1200H ; EGA: Bios alternate select
- mov bl,10H ; Ask for EGA info
- mov bh,0ffH ; Bad info, for testing
- mov cl,0fH ; Reserved switch settings
- int screen ; EGA, are you there?
- and cl,0fh ; four lower switches
- cmp cl,0cH ; Test reserved switch settings
- jb tekin3 ; b = ega present
- jmp tekin7 ; else no EGA, check other adapters
-
- tekin3: mov ax,40h ; check Bios 40:87h for ega being
- mov es,ax ; the active display adapter
- test byte ptr es:[87h],8 ; is ega active?
- jz tekin3a ; z = yes
- jmp tekin7 ; ega is inactive, check others
- tekin3a:cmp bl,1 ; is there 128KB on ega board?
- jb tekin4 ; b = less, so no screen saves
- mov gpage,1 ; >=128 KB, use two graphics pages
- tekin4: mov graph_mode,ega ; assume high resolution color
- cmp cl,3 ; high resolution color?
- je tekin5 ; e = yes
- cmp cl,9 ; high resolution color?
- je tekin5 ; e = yes
- mov graph_mode,monoega ; assume mono monitor on ega board
- test bh,1 ; ega mono mode in effect?
- jnz tekin5 ; nz = yes
- mov graph_mode,colorega ; say ordinary cga on ega board, 64KB
- mov gpage,1 ; is enough memory with 200 scan lines
- jmp short tekin5a ; use current cga parameters
- tekin5: mov ybot,349 ; text screen bottom is 349 on EGA
- mov ymult,35 ;
- mov ydiv,78 ; scale y by 350/780
- tekin5a:mov segscn,segega ; use ega screen segment
- mov psetup,offset psetupe ; plot setup routine
- mov plotptr,offset pltega ; ega dot plot routine
- mov pincy,offset pincye ; inc y routine
- mov putc,offset gputc ; character display routine
- mov gcplot,offset gcega ; EGA character plot routine
- call fixcolor ; correct color mapping for some bds
- jmp tekin13 ; end of EGA part, do VGA tests below
-
- tekin7: mov ax,0fc00h ; Olivetti/AT&T 6300, check rom id
- mov es,ax
- mov di,0 ; start here
- mov graph_mode,olivetti ; Olivetti
- mov cx,attlen ; length of logo
- mov si,offset ATTLOGO ; master string
- repe cmpsb ; do a match
- je tekin7c ; e = a match
- mov di,0050h ; look here too
- mov si,offset ATTLOGO
- mov cx,attlen
- repe cmpsb
- je tekin7c ; e = a match
- mov di,2014h ; and look here
- mov si,offset ATTLOGO
- mov cx,attlen
- repe cmpsb ; do a match
- je tekin7c ; e = a match, else try other types
- tekin7a:mov graph_mode,toshiba
- mov ax,0f000h ; Check for Toshiba T3100, rom scan
- mov es,ax
- mov di,0014h ; start here
- mov si,offset TOSHLOGO ; master string
- mov cx,toshlen ; length
- repe cmpsb ; do a match
- je tekin7c ; e = a match, else try other types
- tekin7b:mov graph_mode,vaxmate ; DEC VAXmate II
- mov ax,0f000h ; Check for VAXmate II rom signature
- mov es,ax
- mov di,0e000h ; start here
- mov si,offset DECLOGO ; master string
- mov cx,declen ; length
- repe cmpsb ; do a match
- jne tekin7d ; ne = mismatch, try other types
-
- ; Olivetti/AT&T, Toshiba, VAXmate
- tekin7c:mov gpage,0 ; only page 0 with 640 by 400 mode
- mov segscn,segcga ; use cga screen segment (0b800h)
- mov psetup,offset psetupo ; plot setup routine
- mov plotptr,offset pltcga ; cga dot plot routine
- mov pincy,offset pincyh ; inc y routine (Herc style addresses)
- mov putc,offset gputc ; character display routine
- mov gcplot,offset gcgen ; General character plot routine
- mov ybot,399 ; bottom of screen is y = 399
- mov ymult,20 ; vertical scale = 400/780
- mov ydiv,39 ; same as cga setup
- jmp tekin13
-
- tekin7d:cmp curmode,mono ; mono text mode?
- je tekin8 ; e = yes
- jmp tekin11 ; ne = no, try cga
- ; test for Hercules
- tekin8: call scrseg ; get screen segment, test Environment
- cmp tv_mode,0 ; Environment active?
- je tekin8a ; e = no, ok to test for Hercules
- jmp tekin10 ; don't do Herc mode, do Mono
- tekin8a:mov dx,hstatus ; Herc status port
- in al,dx ; read it
- mov bl,al ; save here
- and bl,80h ; remember retrace bit
- mov cx,0ffffh ; do many times (for fast machines)
- tekin8b:mov dx,hstatus ; check status port
- in al,dx
- and al,80h ; select bit
- jmp $+2 ; use a little time
- cmp bl,al ; did it change?
- loope tekin8b ; test again if not
- je tekin10 ; e = no change in bit, not Herc
- mov graph_mode,hercules ; say have Herc board
- mov segscn,seghga ; assume hga screen segment
- mov putc,offset gputc ; character display routine
- mov gcplot,offset gcgen ; General character plot routine
- mov psetup,offset psetuph ; plot setup routine to use
- mov plotptr,offset pltcga ; use cga dot plot routine for Herc
- mov pincy,offset pincyh ; inc y routine
- mov xmult,45 ; Scale TEK to Hercules by 720/1024
- mov xdiv,64 ; so that 0-1023 converts to 0-719
- mov xmax,720-8 ; x-coord of rightmost character
- mov ymult,87 ; vertical scale for Hercules is
- mov ydiv,195 ; 348/780
- mov ybot,347 ; bottom of screen is y = 347
- mov ax,seghga ; segment of Herc video display
- mov es,ax
- mov al,es:[8000h] ; read original contents, page 1
- not byte ptr es:[8000h] ; write new pattern
- mov ah,es:[8000h] ; read back
- not byte ptr es:[8000h] ; restore original contents
- not ah ; invert this too
- cmp ah,al ; same (memory present?)
- jne tekin9 ; ne = not same, no memory there
- mov gpage,1 ; say two pages of display memory
- tekin9: jmp tekin13
- ; set to MONO
- tekin10:mov graph_mode,mono ; force monochrome adapter text
- mov segscn,segmono ; assume mono screen segment
- call scrseg ; Environments: get virtual screen
- mov segscn,ax ; seg returned in ax and es:di
- mov gpage,0
- mov putc,offset mputc ; character display routine
- mov psetup,offset psetupm ; plot setup routine to use
- mov plotptr,offset pltmon ; use hga dot plot routine
- mov pincy,offset pincym ; inc y routine
- mov xmult,5 ; Scale TEK to mono by 640/1024
- mov xdiv,8 ; so that 0-1023 converts to 0-639
- mov xmax,640-8 ; x-coord of rightmost character
- mov ymult,10 ; vertical scale for mono is 200/780
- mov ydiv,39
- mov ybot,200 ; bottom of screen is y = 200 for Bios
- jmp tekin13 ; Uses TEXT mode, for safety
-
- ; test for CGA
- tekin11:mov graph_mode,cga ; set CGA high resolution graphics
- mov segscn,segcga ; CGA screen segment
- jmp tekin13
-
- ; Set Graphics mode
- tekin13:cmp graph_mode,hercules ; Hercules?
- jne tekin14 ; ne = no
- call hgraf ; set Herc graphics mode, clear regen
- jmp short tekin16 ; restore screen
- tekin14:mov ah,0 ; set screen mode
- mov al,graph_mode ; to this screen mode
- cmp tekgraf,3 ; user wants "VGA" modes (640x480)?
- jne tekin14a ; ne = no
- cmp al,monoega ; yes, allow high resolution stuff?
- jb tekin14a ; b = no
- cmp al,ega ; ditto
- ja tekin14a ; a = no
- add al,2 ; use modes 17(b/w) and 18(10)(color)
- mov ybot,479 ; text screen bottom is 479 on VGA
- mov ymult,48
- tekin14a:cmp gpage,0 ; only page 0 available?
- je tekin15 ; e = yes, and watch for Bios errors
- cmp inited,0 ; first time through?
- je tekin15 ; e = yes, clear the page of old junk
- or al,80h ; save regen buffer (save area too)
- tekin15:int screen ; Bios Set Mode.
-
- tekin16:mov tekflg,1 ; starting Tek sub mode
- cmp inited,0 ; inited yet?
- jne tekin19 ; ne = yes, restore screen
- mov ttstate,offset tektxt ; do displayable text
- mov prestate,offset tektxt ; set a previous state of text
- mov inited,1 ; say we have initialized
- mov al,gfcol
- mov tfcol,al ; remember current coloring
- mov al,gbcol
- mov tbcol,al
- call tekcls ; clear screen, for ega coloring
- jmp short tekin20
- tekin19:call tekrest ; restore old graphics screen
- mov al,tfcol ; and coloring
- mov gfcol,al
- mov al,tbcol
- mov gbcol,al
- tekin20:mov ax,flow ; get flow control word
- xchg ah,al ; get xon into al
- cmp al,0 ; able to send xon?
- je tekin21 ; e = no
- call outmodem ; tell host xon
- tekin21:clc ; clear carry for success
- jmp short tekin23
- tekin22:stc ; set carry for failure
- tekin23:pop es
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- tekini ENDP
-
- TEKRINT proc near ; Tek reinitialization entry point
- mov inited,0 ; do complete reinitialization
- jmp tekini
- TEKRINT endp
-
- ;Terminal emulation. Enter with received character in AL.
-
- TEKEMU PROC NEAR ; main emulator
- cmp tekflg,0 ; Tek mode active yet? (msz call)
- jne tektt1 ; ne = yes
- call tekini ; init now
- mov ttstate,offset tektxt ; initial state
- mov prestate,offset tektxt ; set a previous state of text
- jnc tektt1 ; nc = succeeded
- ret ; else failed to init, just return
- tektt1: and al,7fh ; force Tek chars to be 7 bits
- cmp al,0 ; NUL char?
- je tekign ; e = yes, ignore it before logging
- push ax
- call getflgs ; get msy yflags into al
- mov yflags,al
- test al,capt ; capturing output?
- pop ax
- jz tektt4 ; z = no, forget this part
- push ax ; save char
- call cptchr ; give it captured character
- pop ax ; restore character and keep going
- tektt4: test yflags,trnctl ; debug? if so use tty mode
- jz tektt5 ; z = no
- cmp al,DEL ; DEL char?
- jne tektt4a ; ne = no
- mov al,5eh ; make DEL a caret query mark
- call outscrn
- mov al,3fh ; the query mark
- call outscrn
- jmp short tekign
- tektt4a:cmp al,' ' ; control char?
- jae tektt4b ; ne = no
- push ax
- mov al,5eh ; caret
- call outscrn
- pop ax
- add al,'A'-1 ; make char printable
- tektt4b:call outscrn
-
- tekign: ret ; Ignore this character
-
- tektt5: call tkscan ; scan for "ESC [ ? 3 8 l" exit code
- tektt5a:cmp al,0 ; null char response?
- je tekign ; e = yes, ignore the character
- cmp al,' ' ; control code?
- jb tektt6 ; b = yes, decode
- jmp ttstate ; no, do current state
- ; Control characters:
- tektt6: cmp al,GS ; Line plot command?
- jne tektt7 ; ne = no
- mov visible,0 ; Next move is invisible
- and status,not txtmode ; set status report byte
- mov ttstate,offset tekline ; expect coordinates next
- jmp tektt12
- tektt7: cmp al,RS ; Incremental dot command?
- jne tektt8 ; ne = no
- and status,not txtmode ; set status report
- mov ttstate,offset tekrlin ; expect pen command next
- jmp tektt12
- tektt8: cmp al,FS ; Point plot command?
- jne tektt9 ; ne = no
- mov visible,0 ; next move is invisible
- and status,not txtmode ; set status report byte
- mov ttstate,offset tekpnt
- jmp tektt12
- tektt9: cmp al,US ; assert text mode? [bjh]
- jne tektt10 ; ne = no
- or status,txtmode ; set status report byte
- mov ttstate,offset tektxt ; Go to TEKTXT next time
- mov bypass,0 ; reset bypass condition
- jmp tektt12
- tektt10:cmp al,ESCAPE ; Escape?
- jne tektt11 ; ne = no
- or status,txtmode ; set status report byte
- cmp ttstate,offset tekesc ; already in escape state?
- je tektt14 ; e = yes, nest no further
- push ttstate ; current state
- pop prestate ; save here as previous state
- mov ttstate,offset tekesc ; next state parses escapes
- ret
- tektt11:cmp al,CAN ; Control X? (exits Tek sub mode)
- jne tektt13 ; ne = no, stay in current state
- cmp ttstate,offset tekesc ; ESC Control-X?
- je tektt13 ; yes, parse it in tekesc code
- mov ttstate,offset tektxt ; back to text mode
- test flags.vtflg,tttek ; main Tek emulator?
- jnz tektt12 ; nz = yes, ignore the ^X
- call tekend ; else exit sub mode
- mov tekflg,0 ; clear Tek sub mode flag
- tektt12:mov prestate,offset tektxt ; make previous state text
- tektt14:ret
- tektt13:jmp ttstate ; let someone else worry about this
- TEKEMU ENDP
-
- ; End TEK emulation, recover previous screen
-
- TEKEND PROC NEAR
- cmp tekflg,0 ; Tek sub mode active?
- jne teknd0 ; ne = yes
- ret ; else return as is.
- teknd0: call teksave ; save graphics screen to page 1
- cmp graph_mode,hercules ; Hercules?
- jne teknd1 ; ne = no
- call htext ; yes then set up Hercules text mode
- teknd1: mov ah,0 ; set video mode
- mov al,curmode ; restore previous screen mode
- int screen ; revert to text screen
- call restscr ; restore text screen
- mov dx,cursor ; saved cursor position
- mov bh,0 ; page 0
- mov ah,2 ; set cursor
- int screen
- ret
- TEKEND ENDP
-
- ; State machine active while Tek is active. Senses ESC [ ? 3 8 l to exit
- ; Tek mode and return to either non-sub mode terminal or to a VT102.
- ; Plays back unmatched escape sequences. Enter with character in al.
-
- tkscan proc near
- and al,7fh ; strip high bit
- cmp al,byte ptr tkoff ; start of Tek Off sequence?
- jne tkscn1 ; ne = no
- call tkscn4 ; playback previously matched chars
- mov tkcnt,1 ; count matched chars (one now)
- mov tkoffs,al ; save full character, with high bit
- mov al,0 ; our temporary response
- jmp short tkscnx ; and exit
-
- tkscn1: push bx ; check for char in Tek Off sequence
- mov bx,tkcnt ; number of chars matched in Tek Off
- mov tkoffs[bx],al ; save this char
- cmp al,byte ptr tkoff[bx] ; match expected char in sequence?
- pop bx
- jne tkscn3 ; ne = no, play back partial match
- inc tkcnt ; count new match
- mov al,0 ; our temporary response
- cmp tkcnt,tkofflen ; matched all char in sequence?
- jne tkscnx ; ne = not yet, wait for more
- mov tkcnt,0 ; clear counter
- cmp flags.vtflg,tttek ; are we a full Tek terminal now?
- jne tkscn2 ; ne = no, a submode
- call vtans52 ; toggle terminal type, in msyibm
- tkscn2: mov al,CAN ; simulate arrival of Control-X
- jmp short tkscnx ; all done
-
- tkscn3: call tkscn4 ; playback previously matched chars
- mov tkcnt,0 ; reset to no match and exit
- tkscnx: ret ; common exit
-
- ; local worker procedure
- tkscn4: push ax ; save break char (in al)
- push cx ; playback partial sequence to screen
- mov cx,tkcnt ; number of chars matched before break
- jcxz tkscn4b ; z = none
- push si
- mov si,offset tkoffs ; string to be played back
- tkscn4a:cld
- lodsb ; get a char into al
- push cx
- push si ; save these around tektt5a work
- call tektt5a ; use it
- pop si
- pop cx
- loop tkscn4a ; do all that came in previously
- pop si
- tkscn4b:pop cx
- pop ax ; recover break char
- ret
- tkscan endp
-
-
- TEKTXT proc near ; Dispatch on text characters
- cmp al,DEL ; RUBOUT?
- jne tektx1 ; ne = no
- mov al,bs ; make BS
- jmp short tektx7
- tektx1: cmp al,CR ; carriage return (^M)?
- je tektx9 ; e = yes
- tektx2: cmp al,LF ; line feed (^J)?
- je tektx9 ; e = yes
- tektx3: cmp al,FF ; form feed (^L)?
- jne tektx4 ; ne = no
- call tekcls ; clear the screen
- jmp short tektx8
- tektx4: cmp al,VT ; vertical tab (^K)?
- je tektx7
- cmp al,bell ; bell (^G)?
- jne tektx5 ; ne = no
- call beep
- mov bypass,0 ; clear GIN mode bypass condition
- jmp short tektx8
- tektx5: cmp al,tab ; horizontal tab (^I)?
- je tektx7 ; e = yes
- tektx6: cmp al,BS ; backspace (^H)?
- je tektx7 ; e = yes
- cmp al,' ' ; control char?
- jb tektx8 ; b = yes, ignore it
- tektx7: cmp bypass,0 ; bypass mode off?
- jne tektx8 ; ne = no, it's on so skip display
- call OUTSCRN ; output character to the screen
- tektx8: ret
- tektx9: mov bypass,0 ; clear GIN mode bypass condition
- jmp short tektx7
- TEKTXT endp
-
- ; Process escape sequences. Callable from msz terminal emulator.
- ; Enter with received character in AL. Escape sequences are generally
- ; treated as interruptions to the current plotting/text command. Screen
- ; clearing is the exception by causing a general emulator reset.
- TEKESC PROC NEAR
- mov bypass,0 ; clear GIN mode bypass condition
- mov ttstate,offset tekesc ; in case get here from msz file
- cmp tekflg,0 ; Tek mode active yet? (msz call)
- jne tekesc1 ; ne = yes
- call tekini ; init now
- mov prestate,offset tektxt ; set a previous state of text
- jnc tekesc1 ; nc = succeeded
- ret ; else failed to init, just return
-
- tekesc1:cmp al,'Z' ; ESC-Z Identify?
- jne tekesc2 ; ne = no
- call SENDID ; Send terminal identification
- jmp tekescx
-
- tekesc2:cmp al,FF ; ESC-FF Clear screen?
- jne tekesc3 ; ne = no
- call tekcls ; Clear screen
- mov prestate,offset tektxt ; make previous state text mode
- jmp tekescx ; Return to text mode after ESC-FF
-
- tekesc3:cmp al,ESCZ ; ESC-^Z Enter GIN mode?
- jne tekesc4 ; ne = no
- cmp graph_mode,mono ; Monochrome text mode?
- je tekesc3a ; e = yes, no crosshairs in text mode
- mov bypass,1 ; turn on GIN mode bypass conditon
- call CROSHAIR ; Activate the cross-hairs
- jmp tekescx
- tekesc3a:call beep ; tell the user we are unhappy
- jmp tekescx ; and ignore the command
-
- tekesc4:cmp al,ENQ ; ESC-^E Enquiry for cursor position?
- jne tekesc5 ; ne = no
- mov bypass,1 ; set bypass mode
- call SENDSTAT ; send status
- jmp tekescx
-
- tekesc5:cmp al,CAN ; ESC Control-X?
- jne tekesc6 ; ne = no
- mov bypass,1 ; set bypass condition
- jmp tekescx
-
- tekesc6:cmp al,3fh ; query mark? (ESC ? means DEL)
- jne tekesc7 ; ne = no
- mov al,DEL ; replace with DEL code
- jmp tekescx ; and process it as if received.
-
- tekesc7:cmp al,accent ; accent grave, line pattern series?
- jb tekesc8 ; b = no
- cmp al,65h ; lowercase e?
- ja tekescx ; a = beyond line pattern series
- push bx
- mov bl,al
- sub bl,accent ; remove bias
- and bl,7 ; eight patterns, roll over excess
- mov bh,0
- shl bx,1 ; make this a word index
- mov bx,linetab[bx] ; get line pattern word
- mov linepat,bx ; save in active word
- pop bx ; return to previous mode
-
- tekesc8:cmp al,5bh ; right square bracket?
- jne tekescx ; ne = no
- jmp tekcol ; start coloring scan
-
- tekescx:push ax
- mov ax,prestate ; get previous state
- mov ttstate,ax ; restore it
- or ax,ax ; test for none
- pop ax
- jz go2text ; z = none, use text mode
- clc
- ret ; resume previous state
-
- go2text:mov ttstate,offset tektxt ; Go to TEKTXT next time
- mov lastc,0 ; clear last drawing coordinate flag
- or status,txtmode ; set text mode in status byte
- clc
- ret
- TEKESC ENDP
- ; Parse ESC [ Pn ; Pn m
- ; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
- TEKCOL proc near
- mov word ptr lastd,0 ; clear parsing flags used below
- mov ttstate,offset tekco1 ; resume parsing below
- clc
- ret
- tekco1: cmp lastd,'3' ; units digit in 30 series?
- jne tekco2 ; ne = no
- inc lastd+1 ; count argument
- sub al,'0' ; ascii to binary
- cmp al,7 ; numeric?
- jbe tekco1a ; be = yes
- jmp tekco10 ; a = no, error
- tekco1a:push bx
- mov bl,al
- mov bh,0
- mov al,byte ptr colortb[bx] ; reverse coloring
- pop bx
- and tfcol,not (7) ; retain intensity bit
- or tfcol,al ; remember foreground color
- mov lastd,0 ; clear parsing flag
- ret
-
- tekco2: cmp lastd,'4' ; units digit in 40 series?
- jne tekco4 ; ne = no
- inc lastd+1 ; count argument
- sub al,'0'
- cmp al,7 ; numeric?
- ja tekco10 ; a = no, error
- push bx
- mov bl,al
- mov bh,0
- mov al,byte ptr colortb[bx] ; reverse coloring
- pop bx
- mov tbcol,al ; remember background color
- mov lastd,0 ; clear parsing flag
- ret
-
- tekco4: cmp lastd,0 ; looking for tens digit?
- jne tekco10 ; ne = yes, error
- cmp al,';' ; separator?
- jne tekco5 ; ne = no
- ret ; ignore it
-
- tekco5: cmp al,'0' ; remove intensity, set b/w?
- jne tekco6 ; ne = no
- mov tfcol,7 ; regular white
- mov tbcol,0 ; on black
- inc lastd+1 ; count argument
- ret
-
- tekco6: cmp al,'1' ; intensity bit?
- jne tekco7 ; ne = no
- and tfcol,not (8)
- or tfcol,8 ; set foreground intensity
- inc lastd+1 ; count argument
- ret
-
- tekco7: cmp al,'m' ; end of sequence
- je tekco8 ; e = yes
- cmp al,'3'
- jb tekco10 ; b = not allowed tens digit
- cmp al,'4'
- ja tekco10 ; a = not allowed tens digit
- mov lastd,al ; remember tens digit
- inc lastd+1 ; count argument
- ret
-
- tekco8: cmp lastd+1,0 ; number of ansi arguments, zero?
- ja tekco9 ; a = no, got some
- mov tbcol,0 ; none is same as 0, set b/w
- mov tfcol,7
- tekco9: mov al,tbcol ; success, store coloring
- mov gbcol,al ; set background color
- mov al,tfcol
- mov gfcol,al ; set foreground color
- tekco10:mov word ptr lastd,0 ; clear argument and number of args
- call fixcolor ; do special ega corrections
- mov al,gfcol ; update these in case error
- mov tfcol,al
- mov al,gbcol
- mov tbcol,al
- jmp tekescx ; finish escape state
- TEKCOL endp
-
- ; Revise screen color codes for ega boards with mono displays and limited
- ; memory.
- fixcolor proc near
- cmp graph_mode,ega ; one of these ega modes?
- je fixcol0 ; e = yes
- cmp graph_mode,colorega
- je fixcol0
- cmp graph_mode,monoega
- je fixcol0
- ret ; else ignore color corrections
- fixcol0:mov ah,gfcol
- mov al,gbcol
- cmp graph_mode,monoega ; monochrome display?
- jne fixcol3 ; ne = no
- test al,7 ; bright backgound?
- jnz fixcol1 ; nz = yes
- mov ah,1 ; normal foreground
- test gfcol,8 ; intensity on?
- jz fixcol1 ; z = no
- mov ah,5 ; say bright foreground
- fixcol1:test al,7 ; black backgound?
- jz fixcol2 ; z = yes
- mov al,1 ; regular video
- fixcol2:cmp ah,al ; same color in both?
- jne fixcol3 ; ne = no
- mov ah,1 ; make foreground regular
- mov al,0 ; and background black
- fixcol3:mov gfcol,ah
- mov gbcol,al
- cmp gpage,0 ; minimal memory (64KB mono and ega)?
- ja fixcol4 ; a = no, enough, else strange mapping
- mov al,gfcol ; fix coloring to map planes C0 to C1
- and al,5 ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
- mov ah,al ; make a copy
- shl ah,1 ; duplicate planes C0, C2 in C1, C3
- or al,ah ; merge the bits
- mov gfcol,al ; store proper foreground color
- mov al,gbcol ; repeat for background color
- and al,5
- mov ah,al
- shl ah,1
- or al,ah
- mov gbcol,al
- fixcol4:ret
- fixcolor endp
-
- TEKLINE proc near ; GS line drawing
- call tekxyc ; parse coordinates from input bytes
- jnc teklin1 ; nc = not done yet
- mov cl,visible ; get moveto or drawto variable
- call tekdraw ; move that point
- mov visible,1 ; say next time we draw
- teklin1:ret
- TEKLINE endp
-
- TEKPNT proc near ; FS plot single point
- call tekxyc ; parse coordinates
- jnc tekpnt1 ; nc = not done yet
- mov cl,0 ; do not draw
- call tekdraw ; move to the point
- mov ax,si ; copy starting point to end point
- mov bx,di ; ax,bx,si,di are in PC coordinates
- mov cl,1 ; make plot visible
- call line ; draw the dot
- mov visible,0 ; return to invisibility
- tekpnt1:ret
- TEKPNT endp
-
- ; Decode graphics x,y components. Returns carry set to say have all
- ; components for a line, else carry clear. Understands 4014 lsb extensions.
- ; Permits embedded escape sequences.
- TEKXYC proc near
- cmp al,CR ; Exit drawing on CR,LF,RS,US,FS,CAN
- je tekghx ; e = yes, a cr
- cmp al,LF ; these terminate line drawing cmds
- je tekghx
- cmp al,FS ; <FS>
- je tekghx
- cmp al,RS ; <RS>
- je tekghx
- cmp al,US ; <US>
- je tekghx
- cmp al,CAN ; and <CAN>
- je tekghx ; BUT ignore other control chars
- cmp al,20h ; Control char?
- jb tekgh0 ; b = yes, ignore it
- cmp al,40h
- jb tekgh2 ; 20-3F are HIX or HIY
- cmp al,60h ; 40-5F are LOX (causes beam movement)
- jb tekgh4 ; 60-7F are LOY
- ; Extract low-order 5 bits of Y coord
- mov ah,tek_loy ; Copy previous LOY to MSB (4014)
- mov tek_lsb,ah
- and al,1Fh ; LOY is 5 bits
- mov tek_loy,al
- cmp lastc,loy ; 2nd LOY in a row?
- je tekgh1 ; Yes, then LSB is valid
- mov tek_lsb,0 ; 1st one, clear LSB
- tekgh1: mov lastc,loy ; LOY seen, expect HIX (instead of HIY)
- tekgh0: clc ; c clear = not completed yet
- ret
- tekghx: jmp go2text
-
- ; Extract high-order 5 bits (X or Y, depending on lastc)
- tekgh2: and ax,1Fh ; Just 5 bits
- mov cl,5
- shl ax,cl ; Shift over 5 bits
- cmp lastc,loy ; was last coordinate a low-y?
- je tekgh3 ; e = yes, parse hix
- mov tek_hiy,ax ; this byte has HIY
- mov lastc,hiy
- clc
- ret
- tekgh3: mov tek_hix,ax ; This byte has HIX
- mov lastc,hix
- clc
- ret
- tekgh4: and al,1Fh ; Just 5 bits
- mov tek_lox,al
- mov lastc,lox
- mov ax,tek_hix ; Combine HIX*32
- or al,tek_lox ; with LOX
- mov bx,tek_hiy ; Same for Y
- or bl,tek_loy
- stc ; set c to say completed operation
- ret
- TEKXYC endp
-
- TEKRLIN proc near ; RS relative line drawing
- cmp al,' ' ; Pen up command?
- jne tekrli1 ; ne = no, try pen down
- mov visible,0 ; do invisible movements
- jmp short tekrli2 ; do the command
- tekrli1:cmp al,'P' ; pen down command?
- jne tekrli3 ; ne = no, return to text mode
- mov visible,1 ; set visible moves
-
- tekrli2:mov ax,x_coord ; PC x coordinate of pen
- mov bx,y_coord ; y coordinate
- call pctotek ; get current pen position in Tek coor
- mov cl,0 ; invisible, moveto
- call tekdraw ; move that point, set oldx and oldy
- mov ttstate,offset tekinc ; next get incremental movement cmds
- ret
-
- tekrli3:mov visible,0 ; bad char, reset visibility
- push prestate
- pop ttstate ; restore previous state
- jmp tektt5 ; deal with the break char
- TEKRLIN endp
- ; interpret RS inc plot command byte
- TEKINC proc near ; get movement character and do cmd
- cmp al,'A' ; move right?
- jne tekinc1 ; ne = no
- inc oldx ; adjust beam position
- jmp short tekinc9
- tekinc1:cmp al,'E' ; move right and up?
- jne tekinc2 ; ne = no
- inc oldx
- inc oldy
- jmp short tekinc9
- tekinc2:cmp al,'D' ; move up?
- jne tekinc3 ; ne = no
- inc oldy
- jmp short tekinc9
- tekinc3:cmp al,'F' ; move left and up?
- jne tekinc4 ; ne = no
- dec oldx
- inc oldy
- jmp short tekinc9
- tekinc4:cmp al,'B' ; move left?
- jne tekinc5 ; ne = no
- dec oldx
- jmp short tekinc9
- tekinc5:cmp al,'J' ; move left and down?
- jne tekinc6 ; ne = no
- dec oldx
- dec oldy
- jmp short tekinc9
- tekinc6:cmp al,'H' ; move down?
- jne tekinc7 ; ne = no
- dec oldy
- jmp short tekinc9
- tekinc7:cmp al,'I' ; move right and down?
- jne tekincb ; ne = no, bad command
- inc oldx
- dec oldy
- tekinc9:cmp oldx,0 ; too far left?
- jge tekinc10 ; ge = no
- mov oldx,0 ; else stop at the left margin
- tekinc10:cmp oldx,maxtekx-1 ; too far left?
- jle tekinc11 ; le = no
- mov oldx,maxtekx-1 ; else stop that the left margin
- tekinc11:cmp oldy,maxteky-1 ; above the top?
- jle tekinc12 ; le = no
- mov oldy,maxteky-1 ; else stop at the top
- tekinc12:cmp oldy,0 ; below the bottom?
- jge tekinc13 ; ge = no
- mov oldy,0 ; else stop at the bottom
- tekinc13:mov ax,oldx ; ax is vector x end point
- mov bx,oldy ; bx is vector y end point
- mov cl,visible
- call tekdraw ; move/draw to that point
- ret
- tekincb:push prestate ; bad character, exit inc plot mode
- pop ttstate ; new state is previous state
- mov visible,0
- jmp tektt5 ; reparse the bad char
- TEKINC endp
-
-
- ; Routine to trigger the crosshairs, wait for a key to be struck, and send
- ; the typed char (if printable ascii) plus four Tek encoded x,y position
- ; coordinates and then a carriage return.
- ; ax, cx, xcross, ycross operate in PC coordinates.
-
- CROSHAIR PROC NEAR
- push linepat ; save line drawing pattern
- mov linepat,0ffffh ; reset line type to solid
-
- mov ax,xmax ; right margin minus 7 dots
- add ax,7
- mov temp,ax ; right margin dot
- crosha1:call crosdraw ; draw the cross-hairs
- call iseof ; is stdin at EOF?
- jc crosha2 ; c = yes, exit this mode now
- mov ah,coninq ; DOS, quiet read char
- int dos
- push ax ; save char for later
- call crosdraw ; erase cross hairs
- pop ax
- or al,al ; ascii or scan code returned
- jnz arrow5 ; nz = ascii char returned
-
- call iseof ; is stdin at EOF?
- jc crosha2 ; c = yes, exit this mode now
- mov ah,coninq ; read scan code
- int dos
- cmp al,0 ; Control-Break?
- jne crosha3 ; ne = no, something else
- crosha2:pop linepat ; restore line pattern
- ret ; exit crosshairs mode
-
- crosha3:cmp al,homscn ; is it 'home'?
- jne arrow1 ; ne = no, try other keys
- mov ax,temp ; right margin
- shr ax,1 ; central position
- mov xcross,ax ; save PC coord for crosshair
- mov ax,ybot ; last scan line
- shr ax,1
- mov ycross,ax ; this is the center of the screen
- jmp crosha1 ; home the crosshairs
-
- arrow1: cmp al,lftarr ; left arrow?
- jne arrow2 ; ne = no
- mov cx,-1 ; left shift
- jmp short xkeys
- arrow2: cmp al,rgtarr ; right arrow?
- jne arrow3 ; ne = no
- mov cx,1 ; right shift
- jmp short xkeys
- arrow3: cmp al,uparr ; up arrow?
- jne arrow4 ; ne = no
- mov cx,-1 ; up shift
- jmp short vertkey
- arrow4: cmp al,dnarr ; down arrow?
- jne badkey ; ne = no, ignore it
- mov cx,1 ; down shift
- jmp short vertkey
-
- badkey: call beep ; tell user we don't understand
- jmp crosha1 ; keep going
-
- ; Shifted keys yield ascii keycodes
- arrow5: cmp al,'C' and 1fh ; Control-C?
- je crosha2 ; e = yes, exit crosshairs mode now
- cmp al,shlftarr ; shifted left arrow?
- jne arrow6 ; ne = no
- mov cx,-10 ; big left shift
- jmp short xkeys
- arrow6: cmp al,shrgtarr ; shifted right arrow?
- jne arrow7 ; ne = no
- mov cx,10 ; big right shift
- jmp short xkeys
- arrow7: cmp al,shuparr ; shifted up arrow?
- jne arrow8 ; ne = no
- mov cx,-10 ; big up shift
- jmp short vertkey
- arrow8: cmp al,shdnarr ; shifted down arrow?
- jne charkey ; ne = no, send this key as is
- mov cx,10 ; big down shift
- jmp short vertkey
-
- xkeys: add cx,xcross ; add increment
- jns noxc ; gone too far negative?
- mov cx,0 ; yes - then make it 0
- noxc: cmp cx,temp ; too far right?
- jb xdraw9 ; b = no
- mov cx,temp ; yes - then make it the right
- xdraw9: mov xcross,cx ; new x value for cross hairs
- jmp crosha1 ; and redraw
-
- vertkey:add cx,ycross ; adjust cx
- jns noyc ; gone negative?
- mov cx,0 ; yes then make 0
- noyc: cmp cx,ybot ; too high?
- jb yok
- mov cx,ybot ; make it maximum
- yok: mov ycross,cx ; save new y crosshair
- jmp crosha1 ; and redraw
-
- charkey:call clrbuf ; purge received data to date
- call outmodem ; send the break character
- mov ax,xcross ; set beam to xcross,ycross
- mov bx,ycross ; must convert to Tek coordinates
- call pctotek ; scale from PC screen coord to Tek
- push ax ; save around drawing
- push bx
- mov cx,0 ; just a move
- call tekdraw ; moveto ax,bx in Tek coord
- pop bx ; recover Tek y
- pop ax ; recover Tek x
- call sendpos ; send position report to host
- pop linepat ; recover current line drawing pattern
- mov ttstate,offset tektxt ; Go to TEKTXT next time
- mov lastc,0 ; clear last drawing coordinate flag
- or status,txtmode ; set text mode in status byte
- ret
- CROSHAIR ENDP
-
- ; CROSDRAW draws cross-hairs by XORing cross with picture.
- ; xcross and ycross are in PC coordinates.
- CROSDRAW PROC NEAR
- mov si,xcross ; move to (xcross, ycross-10)
- mov di,ycross
- sub di,10 ; half the size of the cross
- jns crosd1 ; no sign bit means ok
- mov di,0 ; else limit to start of screen
- crosd1: mov ax,si ; next, draw to (xcross, ycross+10)
- mov bx,ycross ; make bottom stroke
- add bx,10
- cmp bx,ybot ; too large?
- jbe crosd2 ; be = no
- mov bx,ybot ; vertical line to (xcross,ybot)
- crosd2: mov cx,0ffh ; invert pixels
- call line ; and draw vertical
- sub si,12 ; move to (xcross-12, ycross)
- jns crosd3 ; no sign means ok
- mov si,0 ; else limit to start of line
- crosd3: mov di,ycross
- mov bx,di
- mov ax,xcross ; draw to (xcross+12, ycross)
- add ax,12
- cmp ax,temp ; temp is right margin, too large?
- jbe crosd4 ; be = no, ok
- mov ax,temp ; max x value
- crosd4: mov cx,0ffh ; set XOR code
- call line ; draw to (xcross+12, ycross)
- ret
- CROSDRAW ENDP
-
- ; SENDPOS sends position of cross-hairs to the host.
- ; ax has Tek X and bx has Tek Y coord of center of crosshair
- SENDPOS PROC NEAR
- push bx ; preserve register
- call sendxy ; send x coord
- pop ax
- call sendxy ; send y coord
- mov al,cr ; follow up with cr
- call outmodem
- ret
- SENDPOS ENDP
-
- ; SENDXY sends value of ax as Tek encoded bytes
- ; ax is in Tek coordinates
- SENDXY PROC NEAR
- shl ax,1
- shl ax,1 ; move all but lower 5 bits to ah
- shl ax,1
- shr al,1
- shr al,1 ; move low five bits to low 5 bits
- shr al,1
- or ah,20h ; make it a printing char as per TEK
- xchg al,ah ; send high 5 bits first
- call outmodem
- xchg al,ah ; then low five bits
- or al,20h
- call outmodem
- xchg ah,al ; al is first sent byte
- ret
- SENDXY ENDP
-
-
- SENDID PROC NEAR ; Pretend VT100 with graphics option
- mov bx,IDSEQ ; Get addr of string
- sndid1: mov al,[bx] ; Get char from sequence
- cmp al,0 ; End of sequence?
- jz sndid0 ; Yes, return
- call OUTMODEM ; Send it out the port
- inc bx
- jmp sndid1
- sndid0: ret
- SENDID ENDP
-
- ; SENDSTAT - send status and cursor position to host
-
- SENDSTAT PROC NEAR
- mov al,STATUS ; get tek status
- or al,20h ; make it printable
- call OUTMODEM ; and send it
- mov ax,oldx ; now send x coordinate (oldx is Tek)
- call SENDXY
- mov ax,oldy ; and y coordinate (oldy is Tek coord)
- call SENDXY
- mov al,cr ; end with a cr
- call OUTMODEM
- ret
- SENDSTAT ENDP
-
- ; routine to send al to the modem port
-
- OUTMODEM PROC NEAR
- push ax
- mov ah,al
- call outchr ; outchr reads from ah
- nop ; ignore errors
- nop
- nop
- pop ax
- ret
- OUTMODEM ENDP
-
- ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
- ; for both input and output.
- pctotek proc near
- mul xdiv ; scale from PC screen coord to Tek
- div xmult
- xchg bx,ax ; save Tek x coord in bx
- neg ax ; y axis. Turn upside down for Tek
- add ax,ybot
- mul ydiv ; scale y from PC screen coord to Tek
- div ymult
- xchg ax,bx ; ax has X, bx has Y in Tek coords
- ret
- pctotek endp
-
- ; Routine to output character in AL to the screen.
-
- OUTSCRN PROC NEAR ; Output one character to the screen
- cmp bypass,0 ; GIN mode bypass off?
- je outscp ; e = yes
- ret ; else ignore characters
- outscp: ; Set Translation Input filter
- cmp rxtable+256,0 ; translation turned off?
- je outsct ; e = yes, no translation
- push bx
- mov bx,offset rxtable ; address of translate table
- xlatb ; new char is in al
- and al,7fh ; retain only lower seven bits
- pop bx
- outsct: mov si,ybot ; get last scan line
- inc si ; number of scan lines
- sub si,y_coord ; minus where char bottom needs to go
- jnc outscc ; nc = enough space for char
- ; else give "More >" message
- push ax ; save current char
- push cx
- mov cx,mormsglen ; characters in More message
- mov ax,cx
- shl ax,1
- shl ax,1
- shl ax,1 ; times 8 bits/character
- neg ax ; (note: leave last char cell empty)
- add ax,xmax ; right justify
- mov x_coord,ax ; set starting x dot
- mov ax,ybot
- mov y_coord,ax ; set starting y line
- mov ccode,1 ; write in foreground colors
- push cx
- mov al,DEL ; fill all pixels
- outscm1:call putc ; write
- loop outscm1
- pop cx
- push cx
- mov al,BS ; backup to overwrite with More text
- outscm2:call putc
- loop outscm2
- pop cx
- mov ccode,0 ; main text in background colors
- mov si,offset moremsg ; give More message
- outsclf:cld
- lodsb ; read a byte from string
- call putc ; display the string
- loop outsclf ; repeat for all string chars
- pop cx
- mov ccode,1 ; restore normal foreground coloring
- call iseof ; EOF on redirected stdin?
- jc outscl3 ; c = yes, proceed anyway
- mov ah,coninq ; read keyboad via DOS
- int dos ; wait for keystroke
- or al,al ; scan code being returned?
- jne outscl3 ; ne = no
- mov ah,coninq ; clear away scan code too
- int dos
- outscl3:call tekcls ; clear the screen
- pop ax ; recover current character
- cmp al,lf ; just a line feed?
- jne outscc ; ne = no, display it
- ret ; else ignore the line feed
-
- outscc: push ax
- mov ax,xmax
- cmp x_coord,ax ; beyond right margin?
- jbe outsc3 ; be = no
- mov al,cr ; else simulate cr/lf
- call putc ; before displaying current char
- mov al,lf
- call putc
- outsc3: pop ax
- call putc ; routine to draw characters
- ret
- OUTSCRN ENDP
-
-
- ; TEKCLS routine to clear the screen.
- ; Entry point tekcls1 clears screen without resetting current point.
- TEKCLS PROC NEAR
- cmp tekflg,0 ; Tek sub mode active yet?
- jne tekcls0 ; ne = yes
- ret ; else ignore this call
- tekcls0:mov x_coord,0 ; starting text coordinates
- mov y_coord,8
- mov oldx,0 ; assumed cursor starting location
- mov oldy,maxteky ; top right corner (Tek coord)
- mov scalex,0 ; clear last plotted point (PC coord)
- mov scaley,0
- mov lastc,0 ; last parsed x,y coordinate
- mov visible,0 ; make lines invisible
- mov linepat,0ffffh ; reset line pattern to solid
- mov ccode,1 ; reset to ordinary writing
- mov bypass,0 ; clear bypass condition
- mov ttstate,offset tektxt ; do displayable text
- push ax
- mov ax,xmax ; right margin minus 7 dots
- add ax,7 ; right most dot
- shr ax,1 ; central position
- mov xcross,ax ; save PC coord for crosshair
- mov ax,ybot ; last scan line
- shr ax,1
- mov ycross,ax ; this is the center of the screen
- pop ax
-
- tekcls1:push ax ; save registers
- push cx
- cmp graph_mode,hercules ; Hercules?
- jne tekcls2 ; ne = no
- call hgraf ; set Hercules board to Graphics mode
- jmp tekcls7
-
- tekcls2:mov di,0 ; point to start of screen, di=row
- call psetup ; setup graphics routine and es:di
- mov cx,4000h ; CGA, 200 lines times 80 bytes worth
- cmp graph_mode,cga ; cga?
- je tekcls3 ; e = yes
- mov cx,8000h ; Olivetti, 400 lines times 80 bytes
- cmp graph_mode,olivetti ; AT&T-Olivetti?
- je tekcls3 ; e = yes
- cmp graph_mode,toshiba ; Toshiba?
- je tekcls3 ; e = yes
- cmp graph_mode,vaxmate ; VAXmate?
- jne tekcls4 ; ne = no
- tekcls3:cld ; clear screen directly of text stuff
- mov al,0 ; color is black
- rep stosb ; clear the bytes
- jmp short tekcls7
-
- tekcls4:cmp graph_mode,ega ; EGA?
- je tekcls5 ; e = yes
- cmp graph_mode,monoega ; EGA with mono display?
- je tekcls5 ; e = yes
- cmp graph_mode,colorega ; EGA with medium resolution monitor?
- je tekcls5 ; e = yes
- jmp short tekcls6 ; else use Bios
-
- tekcls5: ; EGA clear screen quickly
- mov ax,0ff08h ; set all 8 bits to be changed
- call ega_gc ; set bit mask register accordingly
- mov cx,ybot ; last scan line
- inc cx ; number of scan lines
- mov ax,80 ; bytes per scan line
- mul cx
- mov cx,ax ; cx = number of bytes to clear
- mov al,gbcol ; select background colour
- cld
- rep stosb ; write backgound color
- jmp short tekcls7
-
- tekcls6:push es ; clear screen by scrolling up
- call cmblnk ; clear screen, for Environments
- pop es
-
- tekcls7:mov si,0 ; starting x (in case screen is
- mov di,0 ; starting y cleared by user)
- pop cx
- pop ax
- ret
- TEKCLS ENDP
-
- ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
- ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
- ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
- ; CL=0 - invisible move, CL=1 - draw a line, CL=0FFh - invert pixels on line
-
- TEKDRAW PROC NEAR
- mov si,scalex ; get old x already scaled
- mov di,scaley ; get old y already scaled
- call scale ; scale new end point to PC coords
- cmp cl,0 ; invisible drawing?
- je moveto ; z = just move, skip draw part
- call LINE ; draw the line
- moveto: mov x_coord,ax ; update text coordinates to match
- mov y_coord,bx ; last drawn point
- ret
- TEKDRAW ENDP
-
- ; Scale TEKTRONIX coordinates to the currently defined screen coordinates
- ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
- ; to PC coordinates by this procedure.
- SCALE PROC NEAR
- push dx
- push si
- mov oldx,ax ; save current Tek x for next draw
- mov oldy,bx ; save current Tek y for next draw
- mul xmult ; scale x-coord
- mov si,xdiv ; get the divisor
- shr si,1 ; halve it
- add ax,si ; add in - to round to nearest integer
- adc dx,0
- div xdiv
- push ax
- mov ax,bx
- mul ymult ; scale y-coord
- mov si,ydiv ; get divisor
- shr si,1 ; halve it
- add ax,si ; add in - to round to nearest integer
- adc dx,0
- div ydiv
- mov bx,ybot
- sub bx,ax ; Put new Y in right reg
- jns scale3 ; ns = not too far
- mov bx,0
- scale3: pop ax ; Put new X in right reg
- mov scalex,ax ; save scaled values
- mov scaley,bx
- pop si
- pop dx
- ret
- SCALE ENDP
-
- ; LINE Subroutine to plot a line with endpoints in AX,BX and SI,DI.
- ; fast line drawing routine for the IBM PC
- ;
- ; Registers at CALL
- ; -----------------
- ; SI=Start X coord, all in PC coordinates
- ; DI=Start Y coord
- ; AX=End X coord
- ; BX=End Y coord
- ; CL=Color code: 1=draw foreground, 0=draw background, 0ffh=invert
- ; BP= line drawing pattern (is changed here by rotation)
- ; registers are all unchanged
-
- LINE PROC NEAR
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push es
- mov bp,linepat ; store active line pattern word in BP
- mov ccode,cl ; save color code in ccode for use by plot()
- ; first get coord to achieve increasing x; deltax >= 0
- sub ax,si ; deltax = x2 - x1
- jge line1 ; ge = going to the right, as desired
- neg ax ; make deltax non-negative
- sub si,ax ; swap the x coordinates
- xchg bx,di ; swap the y coordinates too
- ; second, compute deltay. ax = deltax, si = x1
- line1: sub bx,di ; deltay = y2 - y1
- call psetup ; setup display adapter for plotting
- ; and setup es:di to screen memory
- ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
- ; We arrange matters such that both deltas are non-negative.
- cmp bx,0 ; deltay
- jge line2 ; ge = non-negative
- neg linelen
- neg bx ; make non-negative
- line2: cmp bx,ax ; |deltay| versus |deltax|
- jbe shallow ; be = do shallow algorithm
- jmp steep ; else do steep algorithm
-
- ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
- shallow:add bx,bx ; bx = 2*deltay
- mov cx,ax ; cx = number of steps (deltax here)
- inc cx ; loop dec's cx before testing
- mov dx,bx ; dx holds error
- sub dx,ax ; error = 2*deltay - deltax
- add ax,ax ; ax = 2*|deltax|
- shal1: call plotptr ; Plot(x,y)
- cmp dx,0
- jle shal2 ; le = error <= 0
- call pincy ; increment y by one scan line
- sub dx,ax ; error = error - 2*deltax
- shal2: add dx,bx ; error = error + 2*deltay
- inc si ; x = next dot right
- loop shal1
- shal3: jmp short plotex
-
- ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
- steep: add ax,ax ; ax = 2*deltax
- mov dx,ax ; dx holds error
- sub dx,bx ; error = 2*deltax(bx) - deltay (bx)
- mov cx,bx ; cx = number of steps (deltay here)
- inc cx ; loop dec's cx before testing
- add bx,bx ; bx = 2*|deltay|
- stee1: call plotptr ; Plot(x,y) x = ax, y = di
- cmp dx,0
- jle stee2 ; le error <= 0
- inc si ; x = next dot right
- sub dx,bx ; error = error - 2*deltay
- stee2: add dx,ax ; error = error + 2*deltax
- call pincy ; increment y
- loop stee1
- stee3:;;;jmp plotex
-
- plotex: mov ccode,1 ; reset to do foreground coloring
- pop es
- pop di
- pop si
- pop dx ; restore the world
- pop cx
- pop bx
- pop ax
- ret
- LINE ENDP
-
- ;;;;;;; EGA plot support routines
- psetupe proc near ; EGA setup for plotting
- push ax
- mov linelen,80 ; for y going down screen by pincy
- mov ax,segscn ; set es to screen memory segment
- mov es,ax
- mov ax,0205h ; mode: write mode 2
- call ega_gc
- mov ax,0003h ; assume writing bits directly
- cmp ccode,0ffh ; inverting bits?
- jne psete2 ; ne = no
- mov ax,1803h ; then say XOR the bits
- psete2: call ega_gc ; set controller
- mov ax,80 ; compute starting point in regen buff
- mul di
- mov di,ax ; di = di * 80
- pop ax
- ret
- psetupe endp
-
- pincye proc near ; EGA inc y
- add di,linelen ; includes sign of deltay
- ret
- pincye endp
-
- pltega proc near ; EGA plot(x,y). x is in si, y is in di
- rol bp,1 ; rotate line pattern
- jnc pltega1 ; nc = no bit to be plotted
- push bx
- push si
- push di
- mov bx,si ; want si/8 for bytes along line
- shr si,1
- shr si,1
- shr si,1
- add di,si ; starting point in regen buffer
- and bx,0007h ; leave lower 3 bits for bit in byte
- mov bh,masktab[bx] ; 0-7 into bit mask in byte, x pos
- mov bl,ccode ; get line type code
- call ega_plt
- pop di
- pop si
- pop bx
- pltega1:ret
- pltega endp
-
- ;;;;;;;; CGA plot support routines
- ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
- ; left most dot in the high bit, 80 bytes per scan line, scan line segments
- ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
- psetupc proc near ; CGA setup for plotting
- push ax
- push cx
- mov linelen,80 ; 80 bytes per scan line
- mov cx,segscn
- mov es,cx
- mov cx,di ; save copy of di, start y line
- ; compute starting point in regen buff
- shr di,1 ; half the lines in each bank
- mov ax,80 ; 80 bytes per line
- mul di
- mov di,ax ; di = di * 80 / 2
- test cx,1 ; even or odd line
- jz psetc1 ; z = even
- add di,2000h ; offset to odd bank (seg 0ba00h)
- psetc1: and di,3fffh
- pop cx
- pop ax
- ret
- psetupc endp
-
- pincyc proc near ; CGA inc y
- cmp linelen,0 ; increasing or decreasing y?
- jl pinyc2 ; l = decreasing
- cmp di,2000h ; in upper bank now?
- jb pinyc1 ; b = no, in lower bank
- add di,linelen ; add a line
- pinyc1: add di,2000h ; switch banks
- and di,3fffh ; roll over address
- ret
- pinyc2: cmp di,2000h ; in upper bank now?
- jae pinyc4 ; ae = yes
- add di,linelen ; subtract a line
- pinyc4: add di,2000h ; switch banks
- and di,3fffh ; roll over address
- ret
- pincyc endp
-
- pltcga proc near ; CGA plot(x,y). x is in si, y is in di
- push bx ; used for HGA plot also.
- push si
- push di
- rol bp,1 ; rotate line pattern
- jnc pltcg3 ; nc = no bit to be plotted
- mov bx,si ; want si/8 for bytes along line
- shr si,1
- shr si,1
- shr si,1
- add di,si ; starting point in regen buffer
- and bx,0007h ; leave lower 3 bits for bit in byte
- ; di = offset in regen buffer
- mov bh,masktab[bx] ; 0-7 into bit mask in byte. x position
- mov bl,ccode ; get line type code
- cmp bl,1 ; draw the bit?
- jne pltcg1 ; ne = no
- or es:[di],bh ; drawn
- jmp short pltcg3
- pltcg1: cmp bl,0 ; draw in background (erase)?
- jne pltcg2 ; ne = no
- not bh
- and es:[di],bh ; erase the dots
- jmp short pltcg3
- pltcg2: xor es:[di],bh ; xor in this color
- pltcg3: pop di
- pop si
- pop bx
- ret
- pltcga endp
-
- ;;;;;;; HGA plot support routines
- ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
- ; left most dot in the high bit, 90 bytes per scan line, scan line segments
- ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
- ; higher for the rest.
- psetuph proc near ; HGA setup for plotting
- push ax
- push cx
- mov linelen,90 ; for y going down screen by incy
- mov ax,segscn ; base segment of display memory
- mov es,ax
- mov cx,di ; save copy of di, start y line
- ; compute starting point in regen buff
- shr di,1 ; quarter the lines in each bank
- shr di,1
- mov ax,90
- mul di
- mov di,ax ; di = di * 90 / 4
- and cx,3 ; compute bank from 2 lsb of line num
- jcxz pseth2 ; z means it is in bank 0 (0b000h)
- pseth1: add di,2000h ; add offset for each bank
- loop pseth1 ; do cx times
- pseth2: pop cx
- pop ax
- ret
- psetuph endp
-
- pincyh proc near ; HGA inc y, step offset of line
- cmp linelen,0 ; increasing y?
- jg pinyh2 ; g = yes
- cmp di,2000h ; in lowest for four banks?
- ja pinyh1 ; a = no
- add di,linelen ; yes, add a line
- pinyh1: add di,6000h ; move back by adding a lot
- and di,7fffh ; roll over address
- ret
- pinyh2: cmp di,6000h ; in top most bank?
- jb pinyh4 ; b = no
- add di,linelen ; yes, first add a line
- pinyh4: add di,2000h ; switch to next bank
- and di,7fffh ; roll over address
- ret
- pincyh endp
-
- ;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
- ; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
- ; left most dot in the high bit, 80 bytes per scan line, scan line segments
- ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
- ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
- ; writing. This is a monographic display.
- psetupo proc near ; setup for plotting
- push ax
- push cx
- mov linelen,80 ; for y going down screen by incy
- mov ax,segscn ; base segment of display memory
- mov es,ax
- mov cx,di ; save copy of di, start y line
- ; compute starting point in regen buff
- shr di,1 ; quarter the lines in each bank
- shr di,1
- mov ax,80
- mul di
- mov di,ax ; di = di * 80 / 4
- and cx,3 ; compute bank from 2 lsb of line num
- jcxz pseto2 ; z means it is in bank 0 (0b800h)
- pseto1: add di,2000h ; add offset for each bank
- loop pseto1 ; do cx times
- pseto2: pop cx
- pop ax
- ret
- psetupo endp
-
- ;;;;;;;; Monochrome, simulate dots with text char
- psetupm proc near
- mov linelen,1 ; 80 characters but one line
- ret
- psetupm endp
-
- pltmon proc near ; Monochrome dot plot
- mov x_coord,si ; put dot at row=di, col=si, PC Coord
- mov y_coord,di
- push ax
- mov al,'+' ; our dot character
- call mputc ; display text char
- pop ax
- ret
- pltmon endp
-
- pincym proc near ; Monochrome inc y
- add di,linelen ; includes sign
- ret
- pincym endp
-
- ; GPUTC - a routine to send text characters from font to true graphics boards
- ; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
-
- gputc proc near
- cmp al,' ' ; control character?
- jae gputc1 ; ae = no, display the char
- jmp putctrl ; else handle controls at putctrl
- gputc1: push ax ; first save some registers
- push bx
- push cx
- push es
- push di
- mov bl,al ; now BL has char to be displayed
- and bl,7fh ; no high bits allowed here
- ; set board mode
- mov di,y_coord ; get current y coord (char bottom)
- sub di,8 ; start 8 lines higher
- jnc gputc2 ; nc = ok
- mov di,0 ; move up to first line
- mov y_coord,8 ; and reset scan line indicator
- gputc2: call psetup ; enter with di=line number, sets es:di to
- ; start of line in display buf and
- ; sets byte-wide plot mode
- mov ax,x_coord ; compute regen buffer byte
- shr ax,1 ; want x_coord/8 for bytes along line
- shr ax,1
- shr ax,1
- add di,ax ; byte in regen buffer
- xor bh,bh
- sub bx,32 ; characters in font start at 32
- shl bx,1
- shl bx,1 ; 8 bytes per char - hence * 8
- shl bx,1
- mov cx,8 ; 8 bytes (scan lines) to transfer
- call gcplot ; call character plot routine
- call incx ; move to next char position
- pop di
- pop es
- pop cx
- pop bx
- pop ax
- ret
- gputc endp
-
- putctrl proc near ; CONTROL CHARS = cursor movement
- push ax ; save character
- cmp al,FF ; formfeed?
- jne putct0 ; ne = no
- call TEKCLS ; FF clears the screen
- jmp putctx
- putct0: cmp al,BS ; BS? sends (logical) cursor back one
- jne putct2 ; ne = no, try next
- mov ax,x_coord
- sub ax,8 ; so delete 8 dots (move left)
- jns putct1 ; ns = non-negative
- mov ax,0 ; but not less than 0
- putct1: mov x_coord,ax ; and replace x coordinate
- mov al,' ' ; send a space
- call putc
- sub x_coord,8 ; restore cursor
- jmp putctx
- putct2: cmp al,tab ; tabs move forward one char position
- jne putct4 ; ne = not a tab
- call incx ; let incx move cursor right one col
- jmp putctx
- putct3: mov x_coord,ax
- jmp putctx
- putct4: cmp al,cr ; <CR> means go to beginning of line
- jne putct5
- mov x_coord,0 ; zero the x coordinate
- jmp putctx
- putct5: cmp al,lf ; <LF> means go down 8 pixels (1 line)
- jne putct7 ; ne = not LF
- add y_coord,8 ; border managed by outscrn and incx
- jmp putctx
- putct7: cmp al,vt ; <VT> move up screen 1 line (8 pixels)
- jne putctx
- sub y_coord,8 ; subtract one line (8 pixels)
- jnc putctx ; nc = space left
- mov y_coord,8 ; else set to top of screen
- putctx: pop ax
- ret
- putctrl endp
-
- mputc proc near ; MONO put char in AL via Bios
- push ax ; updates x_coord,y_coord with
- push bx ; new cursor position
- push cx
- push dx
- mov ah,0 ; marker for cursor setting not needed
- cmp al,' ' ; control code?
- jae mputc1 ; ae = no, printable
- call putctrl ; do cursor arithmetic
- mov ah,1 ; marker to set cursor but no display
-
- mputc1: push ax ; save char and marker
- mov cl,3 ; char cell is 8 x 8 dots
- mov ax,x_coord ; get resulting cursor PC positions
- shr ax,cl
- mov dl,al ; column
- mov ax,y_coord
- sub ax,8 ; minus 8 dots, like other modes
- jnc mputc2 ; nc = non-negative
- mov ax,0 ; else start at the top
- mov y_coord,8 ; here too
- mputc2: shr ax,cl
- mov dh,al ; row
- mov ah,2 ; set cursor to x_coord,y_coord
- mov bh,0 ; page 0
- int screen
- pop ax
- cmp ah,0 ; write a char in al?
- jne mputcx ; ne = no
- mov ah,09h ; write char at cursor postion
- mov cx,1 ; just one char
- mov bh,0 ; page 0
- mov bl,gfcol ; foreground coloring
- int screen
- inc dl ; next column
- mov ah,2 ; set real cursor ahead of last char
- int screen
- call incx ; move logical cursor
- mputcx: pop dx
- pop cx
- pop bx
- pop ax
- ret
- mputc endp
-
- incx proc near ; move the logical cursor right
- mov ax,x_coord ; shift the (logical) cursor right
- add ax,8 ; one character cell
- mov x_coord,ax
- cmp ax,xmax ; at end of the line?
- jbe incx1 ; b = no
- mov x_coord,0 ; wrap to next line
- add y_coord,8 ; next row
- mov ax,ybot ; last scan line
- cmp ax,y_coord ; below bottom line?
- jge incx1 ; ge = no
- mov y_coord,ax ; set to bottom row
- mov al,lf ; simulate a line feed operation
- call outscrn ; invoke More message
- incx1: ret
- incx endp
-
- ; EGA Character plot routine. Enter with bx pointing at font array for char
- ; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
- ; ccode: 0=plot in background colors, 1=foreground, 0ffh=xor with screen
- gcega proc near
- gcega1: mov al,font[bx] ; EGA byte plot: get bits from font
- push bx
- ;;;;; mov bh,0ffh ; write these bits to clear field
- ;;;;; mov bl,0 ; in background coloring
- ;;;;; call ega_plt ; plot a byte
- mov bh,al ; set bit pattern of character
- mov bl,ccode ; plot in back/fore/xor (ccode) colors
- call ega_plt ; byte plot routine for EGA systems
- pop bx
- inc bx ; next byte of char pattern
- call pincy ; next scan line (linelen is preset)
- loop gcega1
- ret
- gcega endp
-
- ; General Character plot routine. Enter with bx pointing at font array for
- ; char, cx = number of bytes in char font, es:di = screen memory.
- ; Worker for gputc.
-
- gcgen proc near
- gcgen1: mov al,font[bx] ; Non-EGA systems: get bits from font
- cmp ccode,1 ; write in foreground?
- je gcgen2 ; e = yes
- xor es:[di],al ; background or xor (same)
- jmp short gcgen3
- ;;;; mov es:[di],al ; write desired pattern (no overwrite)
- gcgen2: OR es:[di],al ; write desired pattern (no overwrite)
- gcgen3: inc bx ; point to next byte of char pattern
- call pincy ; next scan line (linelen is preset)
- loop gcgen1 ; and repeat until complete
- ret
- gcgen endp
-
- ; routines to manipulate ega graphics controller and mode register
- ; command code in al, value in ah - destroys al and dx
-
- ega_gc proc near ; ega graphics controller
- mov dx,3ceh
- out dx,al ; output command code
- inc dx ; dx is now data port
- mov al,ah ; get value to al
- out dx,al ; output value
- ret
- ega_gc endp
- ega_md proc near ; ega mode controller
- mov dx,3c4h
- out dx,al ; output command code
- inc dx ; dx is now data port
- mov al,ah ; get value to al
- out dx,al ; output value
- ret
- ega_md endp
-
- ; Plot eight pixels using an EGA board
- ; Enter with ES:[DI] pointing to screen address of byte,
- ; bh has pattern of bits to be set, bl has attributes:
- ; 0 = draw in background color, 1 = draw in foreground color,
- ; 0ffh = XOR with current dot colors.
- ; registers preserved
-
- ega_plt proc near
- push ax
- push dx
- mov al,8 ; command to set bit mask register
- mov ah,bh ; get bits to be modified (1)
- call ega_gc ; unprotect those bit positions
- mov ah,gfcol ; get foreground colour
- cmp bl,1 ; draw in foreground?
- je ega2 ; ne = no
- mov ah,gbcol ; get grahics background colour
- cmp bl,0ffh ; do an XOR?
- jne ega2 ; ne = no
- mov ah,0ffh ; XOR, touch all color bits
- ega2: mov al,es:[di] ; latch byte
- mov es:[di],ah ; set the byte
- pop dx
- pop ax
- ret
- ega_plt endp
-
- ; routine to set Hercules card to graphics mode - both pages are enabled
-
- HGRAF PROC NEAR
- push ax
- push bx ; save used registers
- push cx
- push si
- mov al,grph ; graph mode
- lea si,gtable ; requires graphics table
- mov bx,0
- mov cx,4000h ; clear 4000h words
- call setmd ; and set the mode
- pop si
- pop cx
- pop bx
- pop ax
- ret
- HGRAF ENDP
-
- ; set Hercules card to text mode
-
- HTEXT PROC NEAR
- push ax
- push bx
- push cx
- push si
- mov al,text ; text mode
- lea si,ttable ; requires text table
- mov bx,0720h ; blank value (space, white on black)
- mov cx,2000 ; whole screen to clear (80*25)
- call setmd ; set the mode
- pop si
- pop cx
- pop bx
- pop ax
- ret
- HTEXT ENDP
-
- ; Hercules mode set - called from HTEXT and HGRAF
-
- SETMD PROC NEAR
- push dx
- push ax
- mov dx,config ; configuration port
- mov al,genable ; allow graphics mode to be set
- out dx,al
- pop ax
- push ax
- push cx ; save count
- mov dx,cntrl ; control port
- out dx,al ; set to text or graphics
- mov dx,index ; send 12 bytes from table to 6845
- mov cx,12 ; number of registers to load
- xor ah,ah ; start with register 0 of 6845
- cld
- setmd1: jmp $+2 ; small pause for hardware
- mov al,ah ; ah is counter
- out dx,al ; set register
- inc dx ; point to data port
- lodsb ; get next byte in table
- jmp $+2 ; small pause for hardware
- out dx,al ; and send to 6845
- inc ah ; next register
- dec dx ; point to register port
- loop setmd1 ; and continue 'til cx=0
- pop cx ; recover count
- cld
- push di
- push es
- mov ax,segscn ; start of screen
- mov es,ax
- xor di,di
- mov ax,bx ; get blanking character
- rep stosw ; store blanking char in whole screen
- pop es
- pop di
- mov dx,cntrl ; now to re-enable screen
- pop ax ; get mode
- or al,scrn_on ; enable screen
- out dx,al
- pop dx
- ret
- SETMD ENDP
-
- teksave proc near ; saves graphics screen from page 0 to page 1
- push si
- push di
- cmp gpage,0 ; only graphics page 0 on display board?
- je teksavx ; e = yes, no saving possible here
- mov si,segscn ; segment (!) of current screen
- cmp graph_mode,ega
- je teksav1
- cmp graph_mode,monoega
- je teksav1
- cmp graph_mode,colorega
- je teksav1
- cmp graph_mode,hercules
- je teksav2
- jmp short teksavx ; else nothing
- teksav1:mov di,segega+800h ; EGA page 1 screen segment
- call egasr ; call common save/restore code
- jmp short teksavx
- teksav2:mov di,seghga+800h ; Hercules page 1 screen segment
- call hgasr ; call common save/restore code
- teksavx:pop di
- pop si
- ret
- teksave endp
-
- tekrest proc near ; saves graphics screen of page 0 in page 1
- push si
- push di
- cmp gpage,0 ; only graphics page 0 on display board?
- jne tekres0 ; ne = no, more so work to do here
- call tekcls1 ; else clear the screen to color it
- jmp short tekresx ; and exit
- tekres0:mov di,segscn ; segment (!) of new graphics screen
- cmp graph_mode,ega
- je tekres1
- cmp graph_mode,monoega
- je tekres1
- cmp graph_mode,colorega
- je tekres1
- cmp graph_mode,hercules
- je tekres2
- jmp short tekresx ; else nothing
- tekres1:mov si,segega+800h ; segment of EGA page 1
- call egasr ; call common save/restore code
- jmp short tekresx
- tekres2:mov si,seghga+800h ; segment of Hercules page 1
- call hgasr ; call common save/restore code
- tekresx:pop di
- pop si
- ret
- tekrest endp
-
- egasr proc near ; common code for Tek ega save/restore ops
- push ax
- push cx
- push dx
- mov ax,0f00h ; enable 4 plane set/resets
- call ega_gc ; set controller
- mov ax,0f01h ; enable Set/Reset register
- call ega_gc
- mov ax,0f02h ; set color compare register for 4 planes
- call ega_gc
- mov ax,0905h ; set mode reg: write latches, read mode
- call ega_gc
- mov ax,0ff02h ; enable all planes
- call ega_md
- mov cx,ybot ; last scan line
- inc cx ; number of scan lines
- mov ax,80 ; bytes per scan line
- mul cx
- mov cx,ax
- push es ; save es
- push ds ; save ds
- mov es,di ; destination, set es to video memory
- mov ds,si ; source, set ds to video memory
- xor si,si ; clear offset fields
- xor di,di
- cld
- rep movsb ; copy from page [si] to page [di]
- pop ds ; recover ds
- pop es ; and other registers
- mov ax,0000h ; disable 4 plane set/resets
- call ega_gc ; set controller
- mov ax,0001h ; disable Set/Reset register
- call ega_gc ; set controller
- mov ax,0002h ; disable color compare register
- call ega_gc
- mov ax,1005h ; set mode reg: write latches, odd/even
- call ega_gc
- pop dx
- pop cx
- pop ax
- ret
- egasr endp
-
- hgasr proc near ; Hercules save restore screen
- push cx
- mov cx,4000h ; number of words to move
- push es ; save es
- push ds ; save ds
- mov es,di ; destination, set es to video memory
- mov ds,si ; source, set ds to video memory
- xor si,si ; clear offset fields
- xor di,di
- cld
- rep movsw ; copy from page [si] to page [di]
- pop ds ; recover ds
- pop es ; and other registers
- pop cx
- ret
- hgasr endp
- code ends
- end
-